/* 
 * File:   UI.RoundGraph.cpp
 * Author: Jay Sprenkle
 *
 * Created on October 11, 2012
 */
#include "UI.RoundGraph.h"

#include <math.h>

namespace UI
{
   RoundGraph::RoundGraph( QWidget* parent, Qt::WindowFlags f )
      : QWidget( parent, f )
      , m_Value( 0.0f )
      , m_CircleWidth( 12 )
      , m_Alpha( 0.75 )
      , m_BackgroundAlpha( 0.25 )
      , m_CircleWidth2( m_CircleWidth >> 1 )
   {
      m_Color = QColor( Qt::red );
      m_Pen.setColor( m_Color );
      m_Pen.setStyle( Qt::SolidLine );
      m_Pen.setWidth( m_CircleWidth );
      m_Pen.setCapStyle( Qt::RoundCap );

      m_BackgroundColor = QColor( Qt::darkRed );
      m_BackgroundPen.setColor( m_BackgroundColor );
      m_BackgroundPen.setStyle( Qt::SolidLine );
      m_BackgroundPen.setWidth( m_CircleWidth );
//      m_BackgroundPen.setCapStyle( Qt::RoundCap );
   }

   /**
    * calculate the color of the graph bar
    * @param pct
    * @return
    */
   QColor RoundGraph::DisplayColor( float pct )
   {
      float red = pct / 2.0f;

      float blue = 0.5f - pct;
      blue = blue > 0.0f ? 2.0f * blue : 0.0f;

      float yellow = 1.0f - ( 2.0f * fabs( pct - 0.5f ) );
      yellow = yellow > 0.0f ? yellow : 0.0f;

      // yellow = red + green
      red = red + yellow;
      red = red > 1.0f ? 1.0f : red;
      return QColor( red * 255, yellow * 255, blue * 255 );
   }

   float ToRadians( float angle )
   {
      return (angle * 3.14156f) / 180.0f;
   }

   void RoundGraph::paintEvent( QPaintEvent* event )
   {
      QWidget::paintEvent( event );

      QPainter painter( this );
      painter.setRenderHint( QPainter::Antialiasing );
      painter.setOpacity( m_Alpha );

      // <editor-fold defaultstate="collapsed" desc="Graph Circle">
      QRect CircleRect = painter.viewport();
      CircleRect.adjust( m_CircleWidth2, m_CircleWidth2, -m_CircleWidth2, -m_CircleWidth2 );

      QPoint center = CircleRect.center();
      int32_t radius = CircleRect.width() / 2;
      // calculate minimum angle change that will result in a visible change
      double da = asin( 1.0f / radius );
      // render backward so visual transition at graph top is drawn correctly
      float Start = ToRadians( m_StartAngle );
      float Finish = ToRadians( m_StartAngle + m_SpanAngle );
      float Span = ToRadians( m_SpanAngle );
      for ( float a = Finish; a >= Start; a -= da )
      {
         float pct = ( a - Start ) / Span;
         if ( pct < m_Value )
         {
            m_Pen.setColor( DisplayColor( pct ) );
            painter.setPen( m_Pen );
         }
         else
            painter.setPen( m_BackgroundPen );

         painter.drawPoint( center + QPoint( radius * sin( a ), -radius * cos( a ) ) );
      }

//      // draw foreground arc
////      painter.setBrush( QBrush( m_Color ) );
//      painter.setPen( m_Pen );
//      // The startAngle and spanAngle must be specified in 1/16th of a degree, i.e. a full circle equals 5760 (16 * 360).
//      // Positive values for the angles mean counter-clockwise while negative values mean the clockwise direction. Zero degrees is at the 3 o'clock position.
//      // Start angle (1440) makes 6 o'clock = '0' Value
//      int startAngle = ( m_StartAngle * 16 ) - 1440;
//      int spanAngle = m_TotalSpan * m_Value;
//      painter.drawArc( CircleRect, -startAngle, -spanAngle + ( m_CircleWidth * 16 ) );
//
//      // draw background arc
//      painter.setBrush( QBrush( m_BackgroundColor ) );
//      painter.setPen( m_BackgroundPen );
//      painter.drawArc( CircleRect, -( startAngle + spanAngle ), -( m_TotalSpan - spanAngle ) );
      // </editor-fold>
   }

   // <editor-fold defaultstate="collapsed" desc="Value Property">
   float RoundGraph::getValue()
   {
      return m_Value;
   }

   void RoundGraph::setValue( const float a )
   {
      if ( a >= 0.0f && a <= 1.0f )
      {
         m_Value = a;
         update();
      }
   }
   // </editor-fold>

   // <editor-fold defaultstate="collapsed" desc="StartAngle Property">
   float RoundGraph::getStartAngle()
   {
      return m_StartAngle;
   }

   void RoundGraph::setStartAngle( const float a )
   {
      if ( a >= 0 && a <= 360.0 )
      {
         m_StartAngle = a;
         update();
      }
   }
   // </editor-fold>

   // <editor-fold defaultstate="collapsed" desc="SpanAngle Property">
   float RoundGraph::getSpanAngle()
   {
      return m_SpanAngle;
   }

   void RoundGraph::setSpanAngle( const float a )
   {
      if ( a >= 0 && a <= 360.0 )
      {
         m_SpanAngle = a;
         m_TotalSpan = m_SpanAngle * 16;
         update();
      }
   }
   // </editor-fold>

   // <editor-fold defaultstate="collapsed" desc="Width Property">
   int RoundGraph::getGraphWidth()
   {
      return m_CircleWidth;
   }

   void RoundGraph::setGraphWidth( const int a )
   {
      if ( a >= 0 && a <= ( getGraphWidth() >> 1 ) )
      {
         m_CircleWidth = a;
         m_CircleWidth2 = m_CircleWidth >> 1;

         m_Pen.setWidth( m_CircleWidth );

         update();
      }
   }
   // </editor-fold>

   // <editor-fold defaultstate="collapsed" desc="Color Property">
   QColor RoundGraph::getColor()
   {
      return m_Color;
   }

   void RoundGraph::setColor( const QColor& a )
   {
      m_Color = a;
      m_Pen.setColor( m_Color );
      update();
   }
   // </editor-fold>

   // <editor-fold defaultstate="collapsed" desc="Alpha Property">
   qreal RoundGraph::getAlpha()
   {
      return m_Alpha;
   }

   void RoundGraph::setAlpha( const qreal a )
   {
      if ( a >= 0 && a <= 1.0 )
      {
         m_Alpha = a;
         update();
      }
   }
   // </editor-fold>

   // <editor-fold defaultstate="collapsed" desc="BackgroundColor Property">
   QColor RoundGraph::getBackgroundColor()
   {
      return m_BackgroundColor;
   }

   void RoundGraph::setBackgroundColor( const QColor& a )
   {
      m_BackgroundColor = a;
      m_BackgroundPen.setColor( m_BackgroundColor );
      update();
   }
   // </editor-fold>

   // <editor-fold defaultstate="collapsed" desc="Alpha Property">
   qreal RoundGraph::getBackgroundAlpha()
   {
      return m_BackgroundAlpha;
   }

   void RoundGraph::setBackgroundAlpha( const qreal a )
   {
      if ( a >= 0 && a <= 1.0 )
      {
         m_BackgroundAlpha = a;
         update();
      }
   }
   // </editor-fold>
}
